using System;
using System.IO;
using Hive.Core.Common.Shell;

namespace Hive.Core.Model.Commands
{
    /// <summary>
    /// Base class for commands that act on a hives.
    /// </summary>
    public abstract class BaseHiveCommand : Command
    {
        /// <summary>
        /// Initializes the command.
        /// </summary>
        protected BaseHiveCommand()
        {
        }

        /// <summary>
        /// Gets or sets the hive directory, or null to locate it automatically.
        /// </summary>
        public DirectoryInfo HiveDirectory { get; set; }

        /// <inheritdoc />
        sealed protected override CommandExitCode ExecuteImpl(IHiveManager hiveManager, IShell shell)
        {
            DirectoryInfo hiveDirectory = ResolveHiveDirectory(hiveManager, shell);
            if (hiveDirectory == null)
            {
                shell.Echo(MessageSeverity.Error, string.Format("Could not determine the hive directory for '{0}'.  Please specify the hive directory explicitly.", shell.CurrentDirectory.FullName));
                return CommandExitCode.Failure;
            }

            IHive hive = hiveManager.Open(hiveDirectory);
            return ExecuteWithHive(hiveManager, shell, hive);
        }

        /// <summary>
        /// Executes the command with the hive that was found.
        /// </summary>
        /// <param name="hiveManager">The hive manager, not null.</param>
        /// <param name="shell">The shell, not null.</param>
        /// <param name="hive">The hive directory, not null.</param>
        /// <returns>The command exit code.</returns>
        protected abstract CommandExitCode ExecuteWithHive(IHiveManager hiveManager, IShell shell, IHive hive);

        private DirectoryInfo ResolveHiveDirectory(IHiveManager hiveManager, IShell shell)
        {
            if (HiveDirectory != null)
                return HiveDirectory;

            return hiveManager.FindHiveDirectory(shell.CurrentDirectory);
        }
    }
}